package mylittleinvestigations.CaseInformation;
import java.io.IOException;
import java.util.*;
import mylittleinvestigations.Conversation;
import mylittleinvestigations.Evidence;
import mylittleinvestigations.EvidenceIdPair;
import mylittleinvestigations.Sprite;

public class EvidenceManager
{
    private HashMap<String, Evidence> idToItemDictionary;
    private HashMap<EvidenceIdPair, Conversation> idPairToCombinationConversationDictionary;
    private ArrayList<String> idList;

    private int evidenceCount;
    
    private HashMap<Evidence, Boolean> evidenceToOriginalEnabledStateDictionary;

    public EvidenceManager()
    {
        this.idToItemDictionary = new HashMap<String, Evidence>();
        this.idPairToCombinationConversationDictionary = new HashMap<EvidenceIdPair, Conversation>();
        this.idList = new ArrayList<String>();
    }
    
    private Conversation wrongCombinationConversation;
    
    public Conversation getWrongCombinationConversation() { return this.wrongCombinationConversation; }
    public void setWrongCombinationConversation(Conversation wrongCombinationConversation) { this.wrongCombinationConversation = wrongCombinationConversation; }

    public boolean getHasEvidence()
    {
        return this.evidenceCount > 0;
    }

    public boolean getCanCombineEvidence()
    {
        return this.evidenceCount > 1;
    }

    public void Add(String id, String smallTextureId, String largeTextureId, String name, String description, boolean isProfile)
    {
        this.idToItemDictionary.put(id, new Evidence(smallTextureId, largeTextureId, name, description, isProfile));
        this.idList.add(id);
    }

    public void AddEvidenceCombination(String evidenceId1, String evidenceId2, Conversation conversation)
    {
        this.idPairToCombinationConversationDictionary.put(new EvidenceIdPair(evidenceId1, evidenceId2), conversation);
    }

    public ArrayList<String> GetIds()
    {
        return this.idList;
    }

    public Sprite GetSmallSpriteForId(String id)
    {
        Evidence item = this.idToItemDictionary.get(id);
        return item != null ? item.getSmallSprite() : null;
    }

    public Sprite GetLargeSpriteForId(String id)
    {
        Evidence item = this.idToItemDictionary.get(id);
        return item != null ? item.getLargeSprite() : null;
    }

    public String GetNameForId(String id)
    {
        Evidence item = this.idToItemDictionary.get(id);
        return item != null ? item.getName() : null;
    }

    public String GetDescriptionForId(String id)
    {
        Evidence item = this.idToItemDictionary.get(id);
        return item != null ? item.getDescription() : null;
    }

    public boolean IsEvidenceWithIdProfile(String id)
    {
        Evidence item = this.idToItemDictionary.get(id);
        return item != null ? item.getIsProfile() : false;
    }

    public boolean IsEvidenceWithIdEnabled(String id)
    {
        Evidence item = this.idToItemDictionary.get(id);
        return item != null ? item.getIsEnabled() : false;
    }
    
    public boolean IsEvidenceWithIdVisible(String id)
    {
        Evidence item = this.idToItemDictionary.get(id);
        return item != null ? item.getIsEnabled() && !item.getIsHidden() : false;
    }

    public void EnableEvidenceWithId(String id)
    {
        Evidence item = this.idToItemDictionary.get(id);

        if (item != null)
        {
            item.setIsEnabled(true);
            this.evidenceCount++;
        }
    }

    public void DisableEvidenceWithId(String id)
    {
        Evidence item = this.idToItemDictionary.get(id);

        if (item != null)
        {
            item.setIsHidden(true);
            this.evidenceCount--;
        }
    }

    public Conversation GetConversationForEvidenceCombination(String evidenceId1, String evidenceId2)
    {
        EvidenceIdPair idPair = new EvidenceIdPair(evidenceId1, evidenceId2);
        Conversation conversation = this.idPairToCombinationConversationDictionary.get(idPair);

        if (conversation == null)
        {
            conversation = this.getWrongCombinationConversation();
        }

        return conversation;
    }
    
    public void Reset()
    {
        for (Evidence evidence : this.idToItemDictionary.values())
        {
            evidence.setIsEnabled(this.evidenceToOriginalEnabledStateDictionary.get(evidence));
            evidence.setIsHidden(false);
        }
    }

    void SaveToXml(CaseXmlWriter writer) throws IOException
    {
        writer.StartElement("EvidenceManager");
        
        writer.StartElement("IdToItemDictionary");
        String[] ids = this.idToItemDictionary.keySet().toArray(new String[0]);
        
        for (int i = 0; i < ids.length; i++)
        {
            writer.StartElement("Entry");
            String id = ids[i];
            writer.WriteTextElement("Id", id);
            this.idToItemDictionary.get(id).SaveToXml(writer);
            writer.EndElement();
        }
        
        writer.EndElement();
        
        writer.StartElement("IdPairToCombinationConversationDictionary");
        EvidenceIdPair[] idPairs = this.idPairToCombinationConversationDictionary.keySet().toArray(new EvidenceIdPair[0]);
        
        for (int i = 0; i < idPairs.length; i++)
        {
            writer.StartElement("Entry");
            EvidenceIdPair idPair = idPairs[i];
            idPair.SaveToXml(writer);
            this.idPairToCombinationConversationDictionary.get(idPair).SaveToXml(writer);
            writer.EndElement();
        }
        
        writer.EndElement();
        
        writer.StartElement("IdList");
        
        for (int i = 0; i < this.idList.size(); i++)
        {
            writer.StartElement("Entry");
            writer.WriteTextElement("Id", this.idList.get(i));
            writer.EndElement();
        }
        
        writer.EndElement();
        
        writer.StartElement("WrongCombinationConversation");
        this.wrongCombinationConversation.SaveToXml(writer);
        writer.EndElement();
        
        writer.EndElement();
    }

    EvidenceManager(CaseXmlReader reader)
    {
        this.idToItemDictionary = new HashMap<String, Evidence>();
        this.idPairToCombinationConversationDictionary = new HashMap<EvidenceIdPair, Conversation>();
        this.idList = new ArrayList<String>();
        this.evidenceToOriginalEnabledStateDictionary = new HashMap<Evidence, Boolean>();
        
        reader.StartElement("EvidenceManager");
        
        reader.StartElement("IdToItemDictionary");
        reader.StartList("Entry");
        
        while (reader.MoveToNextListItem())
        {
            String id = reader.ReadTextElement("Id");
            Evidence evidence = new Evidence(reader);
            
            if (evidence.getIsEnabled())
            {
                this.evidenceCount++;
            }
            
            this.idToItemDictionary.put(id, evidence);
            this.evidenceToOriginalEnabledStateDictionary.put(evidence, evidence.getIsEnabled());
        }
        
        reader.EndElement();
        
        reader.StartElement("IdPairToCombinationConversationDictionary");
        reader.StartList("Entry");
        
        while (reader.MoveToNextListItem())
        {
            EvidenceIdPair idPair = new EvidenceIdPair(reader);
            Conversation conversation = new Conversation(reader);
            this.idPairToCombinationConversationDictionary.put(idPair, conversation);
        }
        
        reader.EndElement();
        
        reader.StartElement("IdList");
        reader.StartList("Entry");
        
        while (reader.MoveToNextListItem())
        {
            this.idList.add(reader.ReadTextElement("Id"));
        }
        
        reader.EndElement();
        
        reader.StartElement("WrongCombinationConversation");
        this.wrongCombinationConversation = new Conversation(reader);
        reader.EndElement();
        
        reader.EndElement();
    }
    
    public void markChildSprites() throws CaseParseException
    {
        for (Conversation c : this.idPairToCombinationConversationDictionary.values())
        {
            c.markChildSprites(Case.CommonFilesId);
        }
        
        for (Evidence e : this.idToItemDictionary.values())
        {
            e.markChildSprites(Case.CommonFilesId);
        }
    }
}
